package com.github.baichuan.application.scaffold.domain.organization;


import com.github.baichuan.application.scaffold.jpa.authorization.RoleRepository;
import com.github.baichuan.application.scaffold.jpa.identity.ApplicationMemberRepository;
import com.github.baichuan.application.scaffold.jpa.organization.OrgRepository;
import com.github.baichuan.web.dto.Result;
import com.github.baichuan.application.scaffold.domain.application.Application;
import com.github.baichuan.application.scaffold.domain.application.ApplicationService;
import com.github.baichuan.application.scaffold.dto.org.OrgForm;
import com.github.baichuan.web.error.NoSuchEntityException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
@Transactional(rollbackFor = Exception.class)
public class OrgService {

    @Autowired
    public OrgService(OrgRepository orgRepository, ApplicationService applicationService, RoleRepository roleRepository, ApplicationMemberRepository applicationMemberRepository){
        this.orgRepository = orgRepository;
        this.applicationService = applicationService;
        this.roleRepository = roleRepository;
        this.applicationMemberRepository = applicationMemberRepository;
    }

    private OrgRepository orgRepository;
    private ApplicationService applicationService;
    private RoleRepository roleRepository;
    private ApplicationMemberRepository applicationMemberRepository;

    public Org find(Application application, String uid){
        return orgRepository.find(application, uid).orElseThrow(() -> new NoSuchEntityException("平台" + application.getCode() + "不存在机构" + uid));
    }

    public Result add(String applicationCode, OrgForm form) {
        Optional<Org> duplicationUid = orgRepository.findById(form.getUid().trim());
        if(duplicationUid.isPresent()){
            return Result.fail("机构唯一代码重复");
        }

        Application application = applicationService.findByCode(applicationCode);
        Org parent = StringUtils.isBlank(form.getParentUid()) ? null : find(application, form.getParentUid());
        Optional<Org> duplicationName = orgRepository.find(application, parent, form.getName().trim());
        if(duplicationName.isPresent()){
            return Result.fail("同级机构不能重名");
        }

        Org org = new Org();
        org.setUid(form.getUid());
        org.setApplication(application);
        if(parent != null) {
            org.setTenant(parent.getTenant());
        }
        org.setName(form.getName().trim());
        if(parent != null){
            org.setParent(parent);
        }
        updateBranch(org);
        orgRepository.save(org);

        return Result.success("机构添加成功");
    }

    public Result edit(String applicationCode, String uid, OrgForm form) {
        Application application = applicationService.findByCode(applicationCode);
        Org org = find(application, uid);

        Org parent = null;
        if(form.getParentUid() != null){
            parent = find(application, form.getParentUid());

            if(parent.getBranch().contains(org.getUid())){
                return Result.fail("不能添加循环引用");
            }
        }

        org.setParent(parent);
        org.setName(form.getName().trim());
        updateBranch(org);
        updateChildrenBranch(org);

        orgRepository.save(org);
        return Result.success("机构保存成功");
    }

    public Result remove(String applicationCode, String uid) {
        Application application = applicationService.findByCode(applicationCode);
        Org org = find(application, uid);

        if (orgRepository.findChildren(org).size() > 0) {
            return Result.fail("机构下有子机构，不可删除");
        }

        if (applicationMemberRepository.existsByOrg(org)) {
            return Result.fail("机构有关联的账号，不可删除");
        }

//        List<Role> roles = roleRepository.getByTenant(org.getTenant());
//        if(roles.size() > 0){
//            roleRepository.deleteAll(roles);
//        }

        orgRepository.delete(org);
        return Result.success("机构删除成功");
    }

    private void updateBranch(Org org){
        if (org.getParent() != null) {
            org.setBranch(org.getParent().getBranch() + org.getUid() + ",");
        } else {
            org.setBranch(org.getUid() + ",");
        }
    }


    /**
     * 递归修改子机构branch
     * @param parent
     */
    private void updateChildrenBranch(Org parent){
        for (Org child : orgRepository.findChildren(parent)) {
            child.setBranch(parent.getBranch() + child.getUid() + ",");
            updateChildrenBranch(child);
        }


//        List<Org> children = orgRepository.findChildren(oldBranch);
//        String oldParentUid = null;
//        if(null != oldParent){
//            oldParentUid = oldParent.getUid();
//        }
//        String newParentUid = null;
//        if(null != newParent){
//            newParentUid = newParent.getUid();
//        }

//        //父机构调整为顶点机构
//        if(null != oldParentUid && null == newParentUid){
//            for(Org org : children){
//                String oldParentBranch = oldParent.getBranch();
//                String newBranch = org.getBranch().replaceAll(oldParentBranch,"");
//                orgRepository.updateBranch(newBranch, org.getUid());
//            }
//        }
//
//        //父机构添加父机构
//        if(null == oldParentUid && null != newParentUid){
//            for(Org org: children){
//                String newParentBranch = newParent.getBranch();
//                String newBranch = newParentBranch + org.getBranch() + ",";
//                orgRepository.updateBranch(newBranch, org.getUid());
//            }
//        }
//
//        //父机构修改父机构
//        if(null != oldParentUid && null != newParentUid){
//            for(Org org : children){
//                String newParentBranch = newParent.getBranch();
//                String oldParentBranch = oldParent.getBranch();
//                String newBranch = org.getBranch().replaceAll(oldParentBranch,newParentBranch);
//                orgRepository.updateBranch(newBranch, org.getUid());
//            }
//        }
    }

//    public List<Org> getByApplicationCode(String applicationCode) {
//        Application application = applicationService.find(applicationCode);
//        return orgRepository.findByApplication(application);
//    }
}
